import {
  ExclamationCircleOutlined,
  CheckCircleOutlined,
  CloseCircleOutlined,
} from '@ant-design/icons'
import { getLogger } from '@gnlab/utils'
import { App, Alert, Input, Button } from 'antd'
import { Modal } from '@/desktop/components'
import { useCopy } from '@/desktop/logics/copy'
import { colors } from '@/desktop/styles'
import useUIMemory from '@/logics/memory'
import { resetAppsCorpServer, type CorpDetail } from '../logics/index'
import { appGuide } from './callback-guide/index'

const logger = getLogger('ui/qywx-connect/dns')

export function CallbackInfo({
  detail,
  loadDetail,
  edit,
}: {
  detail: CorpDetail
  loadDetail: () => void
  edit: (detail: CorpDetail) => void
}) {
  const copy = useCopy()
  const appsInfo = detail.appsInfo ?? null

  const [corpDomains, setCorpDomains] = useUIMemory<Record<string, string>>('corp-domains', {})
  const appBaseDomain = corpDomains[detail.corpId] ?? ''
  function setAppBaseDomain(value: string) {
    setCorpDomains({ ...corpDomains, [detail.corpId]: value })
  }

  const appResolveIP = '106.54.87.45' // apps.gnlab.com 的 IP
  const appDomainPrefix = 'gnlab666'
  const appDomain = `${appDomainPrefix}.${appBaseDomain.trim() || '你的域名'}`
  const pushURLPath = `/qywxexternalchange/${detail.corpId}`
  const pushURL = appsInfo ? `http://${appDomain}${pushURLPath}` : ''

  const empty = <span css={s.empty}>无</span>

  const [showGuide, setShowGuide] = useState(false)
  const confirmResetServer = useConfirmResetModal(detail, loadDetail)

  return <>
    {!appsInfo ? (
      <Alert
        css={s.warning}
        type="warning"
        showIcon
        message={
          <>
            <span>企业信息不完整，需补充完整后，才能生成事件回调配置。</span>
            <a style={{ marginLeft: '8px' }} onClick={() => edit(detail)}>
              点此补充
            </a>
          </>
        }
      />
    ) : null}

    <div className="row" css={s.desc}>
      <div>
        在企微后台新建 “自建应用”，并在应用的 “接收消息服务器配置” 里，填入以下内容。
        <a onClick={() => setShowGuide(true)}>具体步骤</a>
      </div>
      <div className="tips">
        因企业微信限制，不支持在“客户联系”里配置回调。不然会有部分消息接收不到。
      </div>
    </div>

    <div className="row">
      <label>域名</label>
      {appsInfo ? (
        <>
          <Input
            css={s.appDomain}
            prefix={appDomainPrefix + '.'}
            placeholder="你的域名"
            value={appBaseDomain}
            onChange={e => setAppBaseDomain(e.target.value)}
          />
          <DNSConfirm domain={appDomain} />
        </>
      ) : (
        empty
      )}
    </div>

    <div className="row">
      <label>域名解析 IP</label>
      <span>{appResolveIP}</span>
      <a onClick={() => copy(appResolveIP)}>复制</a>
    </div>

    <div className="row">
      <label>URL</label>
      {appsInfo ? <span>{pushURL}</span> : empty}
      {appsInfo ? <a onClick={() => copy(pushURL)}>复制</a> : null}
    </div>
    <div className="row">
      <label>Token</label>
      {appsInfo ? <span>{appsInfo.cryptToken}</span> : empty}
      {appsInfo ? <a onClick={() => copy(appsInfo.cryptToken)}>复制</a> : null}
    </div>
    <div className="row">
      <label>EncodingAESKey</label>
      {appsInfo ? <span>{appsInfo.cryptKey}</span> : empty}
      {appsInfo ? <a onClick={() => copy(appsInfo.cryptKey)}>复制</a> : null}
    </div>
    {appsInfo ? (
      <div className="row">
        <label></label>
        <a onClick={confirmResetServer}>重新生成 Token 和 EncodingAESKey</a>
      </div>
    ) : null}

    <Modal
      title="在“自建应用”中设置事件回调"
      width={700}
      footer={null}
      onCancel={() => setShowGuide(false)}
      open={showGuide}
    >
      {appGuide(appDomainPrefix, appBaseDomain, appResolveIP)}
    </Modal>
  </>
}

function DNSConfirm({ domain }: { domain: string }) {
  const [status, setStatus] = useState<0 | 1 | 2 | 3>(0) // 0 未检测；1 检测中；2 通过；3 未通过

  async function confirm() {
    setStatus(1)
    try {
      const res = await fetch(`http://${domain}/api/auth/services`)
      if (res.status === 200) {
        const data = (await res.json()) as Record<string, unknown>
        if ('data' in data && 'errcode' in data && 'errmsg' in data) {
          setStatus(2)
          return
        } else {
          logger.warn('数据格式不符合预期', data)
        }
      } else {
        logger.warn('status', res.status)
      }
    } catch (e) {
      logger.error('请求失败', e)
    }
    setStatus(3)
  }

  if (status === 0) {
    return <Button type="link" onClick={confirm}>
      检查域名解析
    </Button>
  } else if (status === 1) {
    return <Button type="link" loading>
      检查中...
    </Button>
  } else if (status === 2) {
    return <div css={s.dnsResult}>
      <div className="info success">
        <CheckCircleOutlined />
        <span className="text">已正确解析</span>
      </div>
      <a onClick={confirm}>重新检查</a>
    </div>
  } else {
    return <div css={s.dnsResult}>
      <div className="info failed">
        <CloseCircleOutlined />
        <span className="text">未通过检查</span>
      </div>
      <a onClick={confirm}>重新检查</a>
    </div>
  }
}

function useConfirmResetModal(detail: CorpDetail, loadDetail: () => void) {
  const { modal, message } = App.useApp()
  return () => {
    modal.confirm({
      title: '重置参数',
      icon: <ExclamationCircleOutlined />,
      content: '重置后需要将新的 Token 和 EncodingAESKey 更新至企业微信后台，确认要重置吗？',
      okText: '确认',
      cancelText: '取消',
      async onOk() {
        // eslint-disable-next-line no-async-promise-executor
        return new Promise<void>(async (resolve: () => void) => {
          const result = await resetAppsCorpServer(detail.corpId)
          if (result.success) {
            void message.success('重置成功')
            void loadDetail()
            resolve()
          } else {
            void message.error('重置失败：' + result.error.message)
          }
        })
      },
    })
  }
}

const s = {
  warning: css`
    margin-bottom: 22px;
  `,
  desc: css`
    margin-bottom: 28px !important;
    display: block !important;
    .tips {
      padding-top: 4px;
      color: ${colors.gray};
    }
  `,
  empty: css`
    color: #ccc;
  `,
  appDomain: css`
    width: 20em;
    margin-top: -4px;
    .ant-input-prefix {
      color: #999;
      margin-right: 0;
    }
  `,
  dnsResult: css`
    align-items: center;
    column-gap: 15px;
    display: flex;
    margin-left: 20px;
    .info {
      align-items: center;
      display: flex;
    }
    .anticon {
      font-size: 16px;
      margin-right: 4px;
    }
    .text {
      font-size: 13px;
    }
    .success {
      color: ${colors.success};
    }
    .failed {
      color: ${colors.error};
    }
  `,
}
